package br.com.sms.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.mail.internet.AddressException;

import org.apache.struts2.ServletActionContext;

import br.com.sms.dominio.Cidade;
import br.com.sms.dominio.Destinatario;
import br.com.sms.dominio.MalaDireta;
import br.com.sms.dominio.Mensagem;
import br.com.sms.enuns.TipoMalaDireta;
import br.com.sms.enuns.UF;
import br.com.sms.excecao.SmsException;
import br.com.sms.util.Mensagens;
import br.com.sms.util.MensagensErro;

import com.opensymphony.xwork2.ActionContext;

public class MalaDiretaAction extends Action{

	private List<Mensagem> listaMensagem;
	private UF[] ufs = UF.values();
	private TipoMalaDireta[] tipos = TipoMalaDireta.values();
	private String nomeDest;
	private List<Cidade> cidades;
	private Cidade cidade;
	private Mensagem mensagem;
	private Set<Destinatario> destinatarios;
	private Set<Destinatario> destinatariosAdicionados;
	private String dest;
	private List<MalaDireta> malasDiretas;
	private MalaDireta malaDireta;
	private UF uf;
	private String siglaUf;
	private Integer codigoTipo;
	
	/**
	 * Recuperar as mensagems para criação da mala direta.
	 * @return
	 */
	public String novaMalaDireta(){
		setMenuAtual(MENU_MALA_DIRETA);
		if(isAdminGeral())
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(null);
		else
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(getCliente());
		this.cidades = new ArrayList<Cidade>();
		getSessao().remove(MALA_SESSAO);
		return TELA_MALA_DIRETA;
	}
	
	/**
	 * Carrega as cidades de acordo com a UF informada.
	 * @return
	 */
	public String carregarCidades(){
		setMenuAtual(MENU_MALA_DIRETA);
		if(siglaUf != null && siglaUf.trim().length() > 0)
			this.uf = UF.newInstance(siglaUf);
		
		this.cidades = getCidadeFacade().carregarCidades(uf);
		if(isAdminGeral())
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(null);
		else
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(getCliente());
		//this.malasDiretas = getMalaDiretaFacade().recuperarMalas(mensagem);
		//ServletActionContext.getRequest().setAttribute("malasDiretas", this.malasDiretas);
		
		this.malaDireta = (MalaDireta)getSessao().get(MALA_SESSAO);
		if(malaDireta != null ){
			this.mensagem = malaDireta.getMensagem();
			this.destinatariosAdicionados = malaDireta.getDestinatarios();
			getRequest().setAttribute("destinatariosAdicionados", this.destinatariosAdicionados);
			getRequest().setAttribute("ufs", this.ufs);
		}
		
		if(isEdicaoMalaDireta())
			return TELA_EDICAO_MALA_DIRETA;
		else
			return TELA_MALA_DIRETA;
	}
	
	
	public String telaMenuMalaDireta(){
		getSessao().remove(MALA_SESSAO);
		return TELA_INICIAL;
	}

	public String filtrarUsuarios(){
			setMenuAtual(MENU_MALA_DIRETA);
		try {
			getDestinatarioFacade().validaCamposMalaDireta(uf, cidade, nomeDest);
			this.destinatarios = getDestinatarioFacade().recuperarDestinatarios(nomeDest, cidade);
			ServletActionContext.getRequest().setAttribute("destinatarios", destinatarios);
			this.siglaUf = uf.getSigla();
		} catch (SmsException e) {
			erros.put("erro", e.getMessage());
			apresentarErros();
		}
		return carregarCidades();
	}

	public String malaDiretaEnviadas(){
		setMenuAtual(MENU_MALA_DIRETA);
		this.malasDiretas = getMalaDiretaFacade().recuperarMalasDiretas(true);
		ServletActionContext.getRequest().setAttribute("malasDiretas", this.malasDiretas);
		return TELA_MALA_ENVIADAS;
	}

	public String adicionarDestinatario(){
		setMenuAtual(MENU_MALA_DIRETA);
		Set<Integer> codigosDestinatarios = getDestinatariosSelecionados();
		if(codigosDestinatarios == null || codigosDestinatarios.size() == 0 && this.malaDireta.getId() == 0){
			filtrarUsuarios();
			erros.put("erro", MensagensErro.SELECIONE_DESTINATARIO);
			apresentarErros();
		}else{

			Set<Destinatario> destinatariosRecuperados = getDestinatarioFacade().recuperarDestinatarios(codigosDestinatarios);
			MalaDireta malaDiretaSessao = (MalaDireta)getSessao().get(MALA_SESSAO);
			if(malaDiretaSessao == null){
				malaDiretaSessao = new MalaDireta();
				this.mensagem = getMensagemFacade().recuperarMensagem(this.mensagem);
				malaDiretaSessao.setMensagem(mensagem);
				malaDiretaSessao.setDestinatarios(destinatariosRecuperados);
			}else{
				for (Destinatario destinatario : destinatariosRecuperados) { 
					if(!malaDiretaSessao.getDestinatarios().contains(destinatario)){
						malaDiretaSessao.getDestinatarios().add(destinatario);
					}
				}
			}
			getSessao().put(MALA_SESSAO, malaDiretaSessao);
			this.destinatariosAdicionados = malaDiretaSessao.getDestinatarios();
			this.destinatarios = getDestinatarioFacade().recuperarDestinatarios(this.nomeDest, cidade);
			atualizarDestinatariosDisponíveis();
			getRequest().setAttribute("destinatariosAdicionados", this.destinatariosAdicionados);
			getRequest().setAttribute("destinatarios", this.destinatarios);
			mensagens.put("mensagem", Mensagens.DESTINATARIOS_ADICIONADOS);
			apresentarMensagens();
			carregarCidades();
		}
		if(isEdicaoMalaDireta())
			return TELA_EDICAO_MALA_DIRETA;
		else
			return TELA_MALA_DIRETA;
	}

	private void atualizarDestinatariosDisponíveis(){
		if(this.destinatariosAdicionados != null && this.destinatariosAdicionados.size() > 0){
			for (Destinatario dest : this.destinatariosAdicionados) {
				if(this.destinatarios != null){
					if(this.destinatarios.contains(dest))
						this.destinatarios.remove(dest);
				}
			}
		}
	}
	
	
	public String salvar(){
		setMenuAtual(MENU_MALA_DIRETA);
		MalaDireta mala = (MalaDireta)getSessao().get(MALA_SESSAO);
		if(mala != null){
			mala.setTipo(TipoMalaDireta.getTipo(this.codigoTipo));
			mala.setDataCriacao(new Date());
			getMalaDiretaFacade().salvar(mala);
			mensagens.put("mensagem", Mensagens.MALA_DIRETA_SALVA);
			apresentarMensagens();
			getSessao().remove(MALA_SESSAO);
		}else{
			erros.put("erro", MensagensErro.SELECIONE_DESTINATARIO);
			apresentarErros();
		}

		return TELA_INICIAL;
	}
	
	
	public String salvarAlteracao(){
		setMenuAtual(MENU_MALA_DIRETA);
		MalaDireta mala = (MalaDireta)getSessao().get(MALA_SESSAO);
		if(mala != null){
			if(mensagem == null || mensagem.getId() == 0){
				erros.put("erro", MensagensErro.CAMPO_OBRIGATORIO.replace("?", "Mensagem"));
				apresentarErros();
				filtrarUsuarios();
				return TELA_EDICAO_MALA_DIRETA;
			}
			mala.setTipo(TipoMalaDireta.getTipo(this.codigoTipo));
			mala.setMensagem(this.mensagem = getMensagemFacade().recuperarMensagem(this.mensagem));
			mala.setDestinatarios(getDestinatarioFacade().recuperarDestinatarios(mala.getDestinatariosIds()));
			mala.setDataCriacao(new Date());
			getMalaDiretaFacade().salvar(mala);
			mensagens.put("mensagem", Mensagens.MALA_DIRETA_ALTERADA);
			apresentarMensagens();
			getSessao().remove(MALA_SESSAO);
		}

		return LISTAR_MALAS_DIRETAS;
	}

	public String cancelar(){
		setMenuAtual(MENU_MALA_DIRETA);
		getSessao().remove(MALA_SESSAO);
		return TELA_INICIAL;
	}

	public String visualizarDestinatarios(){
		setMenuAtual(MENU_MALA_DIRETA);
		this.malaDireta = getMalaDiretaFacade().recuperarMalaDireta(malaDireta);
		this.destinatarios = getDestinatarioFacade().recuperarDestinatarios(this.malaDireta);
		getRequest().setAttribute("destinatarios", destinatarios);
		return TELA_VISUALIZAR_DESTINATARIO;
	}

	//public String 
	public String removerDestinatario(){
		setMenuAtual(MENU_MALA_DIRETA);
		Set<Integer> codigosDestinatarios = getDestinatariosSelecionados();

		if(codigosDestinatarios == null || codigosDestinatarios.size() == 0 && this.malaDireta.getId() == 0){
			filtrarUsuarios();
			erros.put("erro", MensagensErro.SELECIONE_DESTINATARIO);
			apresentarErros();
		}
		else{
			MalaDireta malaDiretaSessao = (MalaDireta)getSessao().get(MALA_SESSAO);
			Set<Destinatario> removidos = getDestinatarioFacade().recuperarDestinatarios(codigosDestinatarios);
			
			for (Destinatario destinatario : removidos) {
				malaDiretaSessao.getDestinatarios().remove(destinatario);
			}

			if(malaDiretaSessao.getDestinatarios().size() > 0)
				this.destinatariosAdicionados = malaDiretaSessao.getDestinatarios();
			
			this.destinatarios = getDestinatarioFacade().recuperarDestinatarios(nomeDest, cidade);
			atualizarDestinatariosDisponíveis();
			getSessao().put(MALA_SESSAO, malaDiretaSessao);
			getRequest().setAttribute("destinatariosAdicionados", this.destinatariosAdicionados);
			getRequest().setAttribute("destinatarios", this.destinatarios);
			mensagens.put("mensagem", Mensagens.DESTINATARIOS_REMOVIDOS);
			apresentarMensagens();
			carregarCidades();
		}
		if(isEdicaoMalaDireta())
			return TELA_EDICAO_MALA_DIRETA;
		else
			return TELA_MALA_DIRETA;

	}

	public String carregarEdicaoMalaDireta(){
		setMenuAtual(MENU_MALA_DIRETA);
		this.malaDireta = getMalaDiretaFacade().recuperarMalaDireta(malaDireta);
		this.mensagem = this.malaDireta.getMensagem();
		this.destinatariosAdicionados =  getDestinatarioFacade().recuperarDestinatarios(malaDireta);
		this.malaDireta.setDestinatarios(this.destinatariosAdicionados);
		malaDireta.setDestinatarios(this.destinatariosAdicionados);
		this.codigoTipo = this.malaDireta.getTipo().getCodigo();
		this.cidades = new ArrayList<Cidade>();
		if(isAdminGeral())
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(null);
		else
			this.listaMensagem = getMensagemFacade().recuperarTodasMensagens(getCliente());
		getRequest().setAttribute("destinatariosAdicionados", this.destinatariosAdicionados);
		getRequest().setAttribute("ufs", this.ufs);
		getSessao().put(MALA_SESSAO, this.malaDireta);

		return TELA_EDICAO_MALA_DIRETA; 
	}

	
	public String excluirMalaDireta(){
		setMenuAtual(MENU_MALA_DIRETA);
		getMalaDiretaFacade().excluirMalaDireta(this.malaDireta);
		mensagens.put("mensagem", Mensagens.MALA_DIRETA_EXCLUIDA);
		apresentarMensagens();
		return LISTAR_MALAS_DIRETAS;
	}

	public String listarMalasDiretas(){
		setMenuAtual(MENU_MALA_DIRETA);
		this.malasDiretas = getMalaDiretaFacade().recuperarMalasDiretas(false);
		getRequest().setAttribute("malasDiretas", this.malasDiretas);
		return TELA_LISTAR_MALAS_DIRETAS;
	}

	public String enviarMalaDireta(){
		setMenuAtual(MENU_MALA_DIRETA);
		this.malaDireta = getMalaDiretaFacade().recuperarMalaDireta(malaDireta);
		this.malaDireta.setDestinatarios(getDestinatarioFacade().recuperarDestinatarios(this.malaDireta));
		try {
			getMalaDiretaFacade().enviarEmail(this.malaDireta);
		} catch (AddressException e) {
			erros.put("erro", MensagensErro.ERRO_ENVIAR_EMAIL);
			apresentarErros();
			return TELA_INICIAL;
		} catch (SmsException e) {
			erros.put("erro", e.getMessage());
			apresentarErros();
			return TELA_INICIAL;
		}
		mensagens.put("mensagem", Mensagens.MALA_DIRETA_ENVIADA);
		apresentarMensagens();
		return TELA_INICIAL;
	}

	private Set<Integer> getDestinatariosSelecionados(){
		Set<Integer> marcados = new HashSet<Integer>();
		//pego todas as chaves dos parâmetros

		Map<String, Object> parametros = ActionContext.getContext().getParameters();

		if(parametros != null){
			for (Object chave : parametros.keySet()){
				//aqueleas que começam por "role-"
				if (String.valueOf(chave).startsWith("dest-")){
					//quebro a String pelo token -, e pego a segunda posicao que contém o saram
					String codigoDest = String.valueOf(chave).split("-")[1];
					//recupero o conteúdo do checkbox
					Object obj = ActionContext.getContext().getParameters().get("dest-"+codigoDest);

					String[] opcao = null;
					//se ele for um String[] é por que foi submetido corretamente
					if (obj instanceof String[]){
						opcao = (String[]) obj;
					}
					//verifico se o conteúdo do checkbox é true, ou seja, foi selecionado
					if (opcao != null && opcao[0].equalsIgnoreCase("true")){
						marcados.add(Integer.parseInt(codigoDest));
					}
				}
			}
		}
		return marcados;
	}
	
	private boolean isEdicaoMalaDireta(){
		MalaDireta direta = (MalaDireta)getSessao().get(MALA_SESSAO);
		if(direta != null && direta.getId() > 0)
			return true;
		else
			return false;
	}
	
	/*Get & Set*/
	public List<Mensagem> getListaMensagem() {
		return listaMensagem;
	}

	public void setListaMensagem(List<Mensagem> listaMensagem) {
		this.listaMensagem = listaMensagem;
	}

	public UF[] getUfs() {
		return ufs;
	}

	public void setUfs(UF[] ufs) {
		this.ufs = ufs;
	}


	public String getNomeDest() {
		return nomeDest;
	}

	public void setNomeDest(String nomeDest) {
		this.nomeDest = nomeDest;
	}

	public List<Cidade> getCidades() {
		return cidades;
	}

	public void setCidades(List<Cidade> cidades) {
		this.cidades = cidades;
	}

	public Cidade getCidade() {
		return cidade;
	}

	public void setCidade(Cidade cidade) {
		this.cidade = cidade;
	}

	public Mensagem getMensagem() {
		return mensagem;
	}

	public void setMensagem(Mensagem mensagem) {
		this.mensagem = mensagem;
	}

	public Set<Destinatario> getDestinatarios() {
		return destinatarios;
	}

	public void setDestinatarios(Set<Destinatario> destinatarios) {
		this.destinatarios = destinatarios;
	}

	public String getDest() {
		return dest;
	}

	public void setDest(String dest) {
		this.dest = dest;
	}

	public Set<Destinatario> getDestinatariosAdicionados() {
		return destinatariosAdicionados;
	}

	public void setDestinatariosAdicionados(
			Set<Destinatario> destinatariosAdicionados) {
		this.destinatariosAdicionados = destinatariosAdicionados;
	}

	public List<MalaDireta> getMalasDiretas() {
		return malasDiretas;
	}

	public void setMalasDiretas(List<MalaDireta> malasDiretas) {
		this.malasDiretas = malasDiretas;
	}

	public MalaDireta getMalaDireta() {
		return malaDireta;
	}

	public void setMalaDireta(MalaDireta malaDireta) {
		this.malaDireta = malaDireta;
	}

	public UF getUf() {
		return uf;
	}

	public void setUf(UF uf) {
		this.uf = uf;
	}

	public String getSiglaUf() {
		return siglaUf;
	}

	public void setSiglaUf(String siglaUf) {
		this.siglaUf = siglaUf;
	}

	public TipoMalaDireta[] getTipos() {
		return tipos;
	}

	public void setTipos(TipoMalaDireta[] tipos) {
		this.tipos = tipos;
	}

	public Integer getCodigoTipo() {
		return codigoTipo;
	}

	public void setCodigoTipo(Integer codigoTipo) {
		this.codigoTipo = codigoTipo;
	}
	
	

}
